#ifndef FRAMEWORKS_JSON_BASH_H
#define FRAMEWORKS_JSON_BASH_H
#include "core/core.h"
#include "json/json.h"

namespace Json {
template<typename TUInt>
static bool getJsonUInt(const Json::Value &elem, const char *name, TUInt *value) {
   
    const Json::Value &item = elem[name];
    if (&item == &Json::Value::null) {
	*value = 0;
        return false;
    } else if (item.isConvertibleTo(Json::uintValue)) {
        *value = item.asUInt();
        return true;
    } else {
	*value = 0;
        return false;
    }
}

template<typename TInt>
static bool getJsonInt(const Json::Value &elem, const char *name, TInt *value) {
    const Json::Value &item = elem[name];
    if (&item == &Json::Value::null) {
	*value = 0;
        return false;
    } else if (item.isConvertibleTo(Json::intValue)) {
        *value = item.asInt();
        return true;
    } else {
	*value = 0;
        return false;
    }
}

static bool getJsonBool(const Json::Value &elem, const char *name, bool *value) {
    const Json::Value &item = elem[name];
    if (&item == &Json::Value::null) {
        return false;
    } else if (item.isConvertibleTo(Json::booleanValue)) {
        *value = item.asBool();
        return true;
    } else {
        return false;
    }
}

static bool getJsonDouble(const Json::Value &elem, const char *name, double *value) {
    const Json::Value &item = elem[name];
    if (&item == &Json::Value::null) {
        return false;
    } else if (item.isConvertibleTo(Json::realValue)) {
        *value = item.asDouble();
        return true;
    } else {
        return false;
    }
}

static bool getJsonString(const Json::Value &elem, const char *name,
        std::string *value) {
    const Json::Value &item = elem[name];
    if (&item == &Json::Value::null) {
        return false;
    } else if (item.isConvertibleTo(Json::stringValue)) {
        *value = item.asString();
        return true;
    } else {
        return false;
    }
}

static bool getJsonBase64String(const Json::Value &elem, const char *name,
        std::string *value) {
    const Json::Value &item = elem[name];
    if (&item == &Json::Value::null) {
        return false;
    } else if (item.isConvertibleTo(Json::stringValue)) {
        ////*value = ::base64_decode(item.asString());
        //*value = gloox::Base64::decode64(item.asString());
        *value = base::Base64::Decode(item.asString());
        return true;
    } else {
        return false;
    }
}


template<typename T>
class PJVectorBase
{
public:
	PJVectorBase(){}
	virtual ~PJVectorBase(){}
protected:
	typedef T type;
	std::vector<type> values;

public:
	virtual const std::vector<type>& getValues() const{
		return values;
	}
	virtual void fromJsonString(const Json::Value& elem) {	
		if (!elem.isArray()) {
			return;
		}	
		type data;
		for (Json::UInt i = 0; i < elem.size(); ++i) {
			decode(elem[i], data);
			values.push_back(data);	
		}	
	}
	
	virtual bool decode(const Json::Value& elem, type& data) = 0;
public:
	PJVectorBase& operator=(const PJVectorBase& vec){
		this->values = vec.values;
		return *this;
	}
};

template<typename T>
class PJVectors : public PJVectorBase<T>
{
	virtual bool decode(const Json::Value& elem, T& data) {
		data.fromJsonString(elem);
		return true; 
	};
};

template<>
class PJVectors<uint32_t> : public PJVectorBase<uint32_t>
{
	bool decode(const Json::Value& elem, uint32_t& data) {
		data = elem.asUInt();
		return true;
	}
};


template<>
class PJVectors<uint16_t> : public PJVectorBase<uint16_t>
{
	bool decode(const Json::Value& elem, uint16_t& data) {
		data = elem.asUInt();
		return true;
	}
};

template<>
class PJVectors<std::string> : public PJVectorBase<std::string>
{
	bool decode(const Json::Value& elem, std::string& data) {
		data = elem.asString();
		return true;
	}
};




class PJsonDecode
{
public:
	PJsonDecode(){}
	virtual ~PJsonDecode(){}
public:
	virtual void fillJson(Json::Value& value) = 0;
	virtual std::string getData(){
		Json::Value value;
		fillJson(value);
		Json::FastWriter fast_writer;
		return fast_writer.write(value);
	}
};

class PJsonEncode
{
public:
	PJsonEncode():_resCode(0){}
	virtual ~PJsonEncode(){}
public:
	uint32_t _resCode;
	virtual void fromJsonString(const Json::Value& elem)
	{
		_resCode = 7;
		getJsonUInt(elem, "resCode", &_resCode);
	}

	virtual void jsonEncodeError(const Json::Value& elem)
	{
		_resCode = 7;
	}
public:
	PJsonEncode& operator=(const PJsonEncode& encode){
		this->_resCode = encode._resCode;
		return *this;
	}
};



class  IUid
{
public:
	IUid():_uid(0){}
	virtual ~IUid(){}
protected:
	uint32_t _uid;
public:
	uint32_t getUid() const{
		return _uid;
	}
	void setUid(uint32_t uid) {
		_uid = uid;
	}
public:
	IUid& operator=(const IUid& uid){
		this->_uid = uid._uid;
		return *this;
	}
};

class IAccount
{
protected:
	std::string _account;
public:
	std::string getAccount() const{
		return _account;
	}
	void setAccount(const std::string& account) {
		_account = account;
	}

};

//class PJProperties : public sox::Properties
//{
//public:
//	std::string toString() const {
//		sox::PackBuffer bf;
//		sox::Pack pk(bf);
//		this->marshal(pk);
//		return std::string(pk.data(), pk.size());
//	}
//	static PJProperties fromString(const std::string &str) {
//		sox::Unpack up(str.data(), str.size());
//		PJProperties p;
//		p.unmarshal(up);
//		return p;
//	}
//};



class PJsonResString
{
public:
	std::string _resString;
	virtual void fromJsonString(const Json::Value& elem)
	{
		getJsonString(elem, "resString", &_resString);
		getJsonBase64String(elem, "resBase64String", &_resString);
	}

	virtual void jsonEncodeError(const Json::Value& elem)
	{
	}
};

}

#endif
